﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using RemoteTestRunner.Contracts;
using RemoteTestRunner.DataAccess;

namespace ConvertRTRConfig
{
    class Program
    {
        #region Private Attributes

        private static List<Project> _projects;
        private static List<Test> _tests;

        #endregion

        #region Static Methods

        /// <summary>
        /// The application entry point.
        /// </summary>
        /// <param name="args">The command-line arguments.</param>
        static void Main(string[] args)
        {
            if (args.Length != 2)
            {
                ShowUsage();
            }
            else
            {
                Convert(args[0], args[1]);
            }
        }

        /// <summary>
        /// Converts the specified configuration file to the latest version.
        /// </summary>
        /// <param name="sourcePath">The source path of the file to be converted.</param>
        /// <param name="destinationPath">The destination path.</param>
        private static void Convert(string sourcePath, string destinationPath)
        {
            if (!File.Exists(sourcePath))
            {
                throw new FileNotFoundException(
                    "The source file to be converted could not be found.  Please check the path and try again.",
                    sourcePath);
            }

            // Setup collections
            _projects = new List<Project>();
            _tests = new List<Test>();

            // Load old version into DataSet
            var dataSet = new RTRDataSet();

            dataSet.ReadXml(sourcePath, XmlReadMode.ReadSchema);

            // Move DataSet contents to new model
            foreach (RTRDataSet.ProjectRow projectRow in dataSet.Project.Rows)
            {
                var newProject = AddProject(projectRow);
                Console.WriteLine("Adding Project: {0}", newProject.Name);

                foreach (var testRow in projectRow.GetTestRows())
                {
                    var newTest = AddTest(newProject, testRow);
                    Console.WriteLine("\tAdding Test: {0}", newTest.Name);
                }
            }

            // Serialize model into new file
            var dataAccess = new TestProjectAccess(destinationPath);

            dataAccess.SaveProjects(_projects);
        }

        /// <summary>
        /// Adds the "old style" project to the list of "new style" projects.
        /// </summary>
        /// <param name="project">A <see cref="DataRow"/> representing the "old style" project.</param>
        /// <returns>A reference to the newly added project.</returns>
        private static Project AddProject(RTRDataSet.ProjectRow project)
        {
            // Get next available ID...
            var nextProjectId = _projects.Count == 0 ? 1 : _projects.Select(x => x.Id).Max() + 1;

            var newProject = new Project
            {
                Name = project.Name,
                Id = nextProjectId,
                CreatedBy = project.CreatedBy,
                CreatedDate = project.CreatedDate,
                ModifiedBy = project.ModifiedBy,
                ModifiedDate = project.ModifiedDate
            };

            _projects.Add(newProject);

            return newProject;
        }

        /// <summary>
        /// Adds the "old style" test to the list of "new style" tests.
        /// </summary>
        /// <param name="project">The parent project.</param>
        /// <param name="test">A <see cref="DataRow"/> representing the "old style" test.</param>
        /// <returns>A reference to the newly added test.</returns>
        private static Test AddTest(Project project, RTRDataSet.TestRow test)
        {
            // Get next available ID...
            var nextTestId = _tests.Count == 0 ? 1 : _tests.Select(x => x.Id).Max() + 1;
            var newTest = new Test
                              {
                                  Name = test.Name,
                                  Id = nextTestId,
                                  AssemblyPath = System.Convert.IsDBNull(test.AssemblyPath) ? string.Empty : test.AssemblyPath,
                                  ConfigPath = System.Convert.IsDBNull(test.ConfigPath) ? string.Empty : test.ConfigPath,
                                  RunConfigPath = System.Convert.IsDBNull(test.RunConfigPath) ? string.Empty : test.RunConfigPath,
                                  CreatedBy = test.CreatedBy,
                                  CreatedDate = test.CreatedDate,
                                  ModifiedBy = test.ModifiedBy,
                                  ModifiedDate = test.ModifiedDate
                              };

            _tests.Add(newTest);
            project.Tests.Add(newTest);

            return newTest;
        }

        /// <summary>
        /// Shows the usage for this command.
        /// </summary>
        private static void ShowUsage()
        {
            Console.WriteLine("Remote Test Runner configuration conversion utility.\r\n");
            Console.WriteLine("Usage: convert SourceFile DestFile\r\n");
            Console.WriteLine("  SourceFile - An RTR configuration file created for a previous version");
            Console.WriteLine("               of RTR.");
            Console.WriteLine("  DestFile   - Specifies the name of the new RTR config file");
        }

        #endregion
    }
}
